<?php


namespace app\service\order;


use app\common\exception\ApiException;
use app\model\coach\CoachRatioModel;
use app\model\goods\OrderModel;
use app\model\partner\EscortMenuOrderModel;
use app\model\partner\EscortMenuReserveOrderModel;
use app\model\partner\UserPartnerModel;
use app\service\BaseService;
use app\service\config\ConfigService;
use app\service\user\PartnerMoneyRecordService;
use app\service\user\UserService;
use think\facade\Db;

class PartnerOrderService extends BaseService
{
    public function __construct()
    {
        $this->model = new EscortMenuReserveOrderModel();
    }

    /**
     * 完成陪驾订单
     * @param $id
     * @return bool
     * @throws ApiException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function completeOrderService($id)
    {
        $info = $this->model->find($id);
        if (!$info) {
            throw new ApiException('预约信息不存在');
        }
        if ($info['status'] != 3 && $info['status'] != 7) {
            throw new ApiException('订单状态错误');
        }
        $info->status = EscortMenuReserveOrderModel::COMPLETE;
        $info->complete_time = time();
        $info->save();

        // 用户订单完成
        $orderInfo = OrderModel::where('order_sn', $info['order_sn'])->find();
        if ($orderInfo) {
            $orderInfo->order_status = 1;
            $orderInfo->save();
        }

        // 教练加钱
        $userPartnerInfo = UserPartnerModel::find($info['coach_user_id']);
        $classAmount = $info['is_trial'] == 1 ? $userPartnerInfo['trial_class_amount'] : $userPartnerInfo['class_amount'];
        $amount = bcmul($classAmount, $info['duration'], 2);
//        if ($amount > 0) {
        $partnerMoneyRecordService = new PartnerMoneyRecordService();
        $type = PartnerMoneyRecordService::ORDER;
        $title = $partnerMoneyRecordService->getTypeText($type);
        $partnerMoneyRecordService->createLog($title, $info['coach_user_id'], $type, $amount, 0, $info['order_sn']);
//        }
        // 教练是否禁止接单
        if ($userPartnerInfo['is_forbid'] == 1) {
            $count = EscortMenuReserveOrderModel::where('coach_user_id', $info['coach_user_id'])
                ->where('reserve_time', '<=', time())
                ->whereIn('status', [2, 3, 7, 8])
                ->count();
            $minRatio = ConfigService::getConfigValue('min_ratio');
            $maxNum = ConfigService::getConfigValue('max_num');
            if ($count < $maxNum && $userPartnerInfo['ratio'] >= $minRatio) {
                $userPartnerInfo->is_forbid = 0;
            }
        }

        // 教练增加服务次数
        $userPartnerInfo->service_num = Db::raw('service_num+1');
        $userPartnerInfo->accept_order_num = Db::raw('accept_order_num+1');
        $userPartnerInfo->total_duration = Db::raw('total_duration+' . $info['duration']);
        $userPartnerInfo->save();

        // 判断剩余时长 分佣
        $sourceId = $info['source_id'];
        $menuOrderId = $info['order_id'];
        if ($sourceId == 1 && $menuOrderId) {
            $menuOrderInfo = EscortMenuOrderModel::find($menuOrderId);
            if ($menuOrderInfo && $menuOrderInfo['residue_duration'] == 0) {
                // 推荐奖励
                $userService = new UserService();
                $userService->award($menuOrderInfo['user_id'], $menuOrderInfo['amount'], $menuOrderInfo['order_sn']);
            }
        }
        // 订单完成
        self::setPartnerRatio($info['user_id'], $info['is_trial'], $info['coach_user_id']);
        return true;
    }

    /**
     * 重新计算教练转化率
     * @param $userId
     * @param int $isTrail
     * @param int $partnerId
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function setPartnerRatio($userId, $isTrail = 0, $partnerId = 0)
    {
        // 用户是否已经计算过转化率 如果计算过转化率则返回
        $orderInfo = CoachRatioModel::where('user_id', $userId)->where('status', 1)->find();
        if ($orderInfo) {
            return true;
        }
        // 计算转化率的教练ID
        $coachId = 0;
        if ($isTrail == 1) {
            // 体验单先进来  判断用户买过正式课 如果有，直接计算转化率。
            $officialOrder = EscortMenuOrderModel::where('user_id', $userId)
                ->whereIn('pay_status', [2, 3])
                ->where('is_trial', 0)
                ->find();
            if ($officialOrder) {
                $coachRatioModel = new CoachRatioModel();
                $coachRatioModel->coach_id = $partnerId;
                $coachRatioModel->user_id = $userId;
                $coachRatioModel->status = 1;
                $coachRatioModel->save();

                $coachId = $partnerId;
            } else {
                // 如果没有 体验单先进入 不计算转化率
                $coachRatioModel = new CoachRatioModel();
                $coachRatioModel->coach_id = $partnerId;
                $coachRatioModel->user_id = $userId;
                $coachRatioModel->status = 0;
                $coachRatioModel->save();
            }
        } else {
            // 正式课先进来 判断是否有体验课记录 如果有 则记入该教练的转化率
            $coachRatioModel = CoachRatioModel::where('user_id', $userId)->where('status', 0)->find();
            if ($coachRatioModel) {
                $coachRatioModel->status = 1;
                $coachRatioModel->save();

                $coachId = $coachRatioModel['coach_id'];
            }
        }
        if ($coachId) {
            // 未完成数量
            $successCount = CoachRatioModel::where('user_id', $userId)
                ->where('coach_id', $coachId)
                ->where('status', 1)
                ->count();
            // 总数
            $totalCount = CoachRatioModel::where('user_id', $userId)
                ->where('coach_id', $coachId)
                ->count();
            $ratio = bcdiv($successCount * 100, $totalCount, 1);

            $coachUserInfo = UserPartnerModel::find($coachId);
            $coachUserInfo->ratio = $ratio;
            $coachUserInfo->save();
        }
        return true;
    }
}